package org.rulix.ogame.player.core;

import java.io.FileInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.rulix.ogame.player.api.OgamePlanet;
import org.rulix.ogame.player.api.OgamePlanetCoordinates;
import org.rulix.ogame.player.core.info.OgameDataHelper;

public class OgameResponseParser {
	private String htmlStream;
	private Source source;
	
	public OgameResponseParser(String htmlStream) {
		this.htmlStream = htmlStream;
		source = new Source(this.htmlStream);
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// Planets
	///
	public List<OgamePlanet> getPlanets() throws OgameException {
		List<Element> smallplanets = source.getAllElementsByClass("smallplanet");
		List<OgamePlanet> ogamePlanets = Collections.synchronizedList(new ArrayList<OgamePlanet>());
		for (Element element : smallplanets) {
			Element first = element.getFirstElement(HTMLElementName.A);
			String valueHrefPlanet = first.getAttributeValue("href");

			first = element.getFirstElementByClass("planet-koords");
			String koords = first.getContent().toString();
			
			first = element.getFirstElementByClass("planet-name");
			String planetName = first.getContent().toString();
			
			OgamePlanet planet = new OgamePlanet();
			OgamePlanetCoordinates coords = OgamePlanetCoordinates.getCoordinates(koords);
			planet.setName(planetName);
			planet.setCoordinates(coords);
			
			List<NameValuePair> values = null;
			try {
				values = URLEncodedUtils.parse(new URI(valueHrefPlanet), null);
			} catch (URISyntaxException e) {
				throw new OgameException("Wrong planet uri '"+valueHrefPlanet+"'", e);
			}
			for (NameValuePair nameValuePair : values) {
				if(nameValuePair.getName().equals("cp"))
					planet.setCode(nameValuePair.getValue());
			}
			ogamePlanets.add(planet);
		}
		return ogamePlanets;
	}
	
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// RESOURCES
	///
	public long getMetalResources(){
		return getGenericResouces("resources_metal");
	}
	public long getCrystalResources(){
		return getGenericResouces("resources_crystal");
	}
	public long getDeuteriumResources(){
		return getGenericResouces("resources_deuterium");
	}
	
	private long getGenericResouces(String res_id){
		Element e = source.getElementById(res_id);
		if ( e == null )
			return -1L;
		String content = e.getContent().toString();
		
		content = content.replaceAll("[^0-9]", "");
		return Long.parseLong(content.trim());
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// BUILDINGS
	///
	public int getMetalMineLevel(){
		return getGenericLevel("building", "Mina de metal");
	}
	public int getCrystalMineLevel(){
		return getGenericLevel("building", "Mina de cristal");
	}
	public int getDeuteriumSynthLevel(){
		return getGenericLevel("building", "Sintetizador de deuterio");
	}
	public int getSolarPlantLevel(){
		return getGenericLevel("building", "Planta de energía solar");
	}
	public int getFusionPlantLevel(){
		return getGenericLevel("building", "Planta de fusión");
	}
	public int getSolarSatellieLevel(){
		return getGenericLevel("building", "Satélite solar");
	}
	public int getMetalStorageLevel(){
		return getGenericLevel("storage", "Almacén de metal");
	}
	public int getCrystalStorageLevel(){
		return getGenericLevel("storage", "Almacén de cristal");
	}
	public int getDeuteriumStorageLevel(){
		return getGenericLevel("storage", "Contenedor de deuterio");
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// FACILITIES
	///
	
	public int getRobotFactoryLevel(){
		return getGenericLevel("stationbuilding", "Fábrica de Robots");
	}
	
	public int getHangarLevel(){
		return getGenericLevel("stationbuilding", "Hangar");
	}

	public int getResearchLabLevel(){
		return getGenericLevel("stationbuilding", "Laboratorio de investigación");
	}
	
	public int getSiloLevel(){
		return getGenericLevel("stationbuilding", "Silo");
	}
	
	public int getNanobotFactoryLevel(){
		return getGenericLevel("stationbuilding", "Fábrica de Nanobots");
	}
	
	public int getTerraformerLevel(){
		return getGenericLevel("stationbuilding", "Terraformer");
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// SHIPS
	///
	public int getLightFighterQuantity(){
		return getGenericLevel("military", "Cazador ligero");
	}
	
	public int getHeavyFighterQuantity(){
		return getGenericLevel("military", "Cazador pesado");
	}
	
	public int getCruiserQuantity(){
		return getGenericLevel("military", "Crucero");
	}
	
	public int getBattleShipQuantity(){
		return getGenericLevel("military", "Nave de batalla");
	}
	
	public int getBattleCruiserQuantity(){
		return getGenericLevel("military", "Acorazado");
	}
	
	public int getBomberQuantity(){
		return getGenericLevel("military", "Bombardero");
	}
	
	public int getDestroyerQuantity(){
		return getGenericLevel("military", "Destructor");
	}
	
	public int getDeathStarQuantity(){
		return getGenericLevel("military", "Estrella de la muerte");
	}
	
	public int getSmallCargoQuantity(){
		return getGenericLevel("civil", "Nave pequeña de carga");
	}
	
	public int getLargeCargoQuantity(){
		return getGenericLevel("civil", "Nave grande de carga");
	}
	
	public int getColonyShipQuantity(){
		return getGenericLevel("civil", "Colonizador");
	}
	
	public int getRecyclerQuantity(){
		return getGenericLevel("civil", "Reciclador");
	}
	
	public int getEspionageProbeQuantity(){
		return getGenericLevel("civil", "Sonda de espionaje");
	}
	
	public int getSolarSatelliteQuantity(){
		return getGenericLevel("civil", "Satélite solar");
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// RESEARCH
	///
	public int getEnergyTechnology(){
		return getGenericLevel("base", "Tecnología de energía");
	}
	
	public int getLaserTechnology(){
		return getGenericLevel("base", "Tecnología láser");
	}
	
	public int getIonTechnology(){
		return getGenericLevel("base", "Tecnología iónica");
	}
	
	public int getHyperSpaceTechnology(){
		return getGenericLevel("base", "Tecnología de hiperespacio");
	}
	
	public int getPlasmaTechnology(){
		return getGenericLevel("base", "Tecnología de plasma");
	}
	
	public int getCombustionDrive(){
		return getGenericLevel("base2", "Motor de combustión");
	}
	
	public int getImpulseDrive(){
		return getGenericLevel("base2", "Motor de impulso");
	}
	
	public int getHyperSpaceDrive(){
		return getGenericLevel("base2", "Propulsor hiperespacial");
	}
	
	public int getEspionageTechnology(){
		return getGenericLevel("base3", "Tecnología de espionaje");
	}
	
	public int getComputerTechnology(){
		return getGenericLevel("base3", "Tecnología de computación");
	}
	
	public int getAstrophysics(){
		return getGenericLevel("base3", "Astrofísica");
	}
	
	public int getIntergalacticResearchNetwork(){
		return getGenericLevel("base3", "Red de investigación intergaláctica");
	}
	
	public int getGravitonTechnology(){
		return getGenericLevel("base3", "Tecnología de gravitón");
	}
	
	public int getWeaponTechnology(){
		return getGenericLevel("base4", "Tecnología militar");
	}
	
	public int getShieldingTechnology(){
		return getGenericLevel("base4", "Tecnología de defensa");
	}
	
	public int getArmourTechnology(){
		return getGenericLevel("base4", "Tecnología de blindaje");
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// DEFENSES
	///
	public int getRocketLauncherQuantity(){
		return getGenericLevel("defensebuilding", "Lanzamisiles");
	}
	
	public int getLightLaserQuantity(){
		return getGenericLevel("defensebuilding", "Láser pequeño");
	}
	
	public int getHeavyLaserQuantity(){
		return getGenericLevel("defensebuilding", "Láser grande");
	}
	
	public int getIonCannonQuantity(){
		return getGenericLevel("defensebuilding", "Cañón iónico");
	}
	
	public int getGaussCannonQuantity(){
		return getGenericLevel("defensebuilding", "Cañón Gauss");
	}
	
	public int getPlasmaTurretQuantity(){
		return getGenericLevel("defensebuilding", "Cañón de plasma");
	}
	
	public int getSmallShieldDome(){
		return getGenericLevel("defensebuilding", "Cúpula pequeña de protección");
	}
	
	public int getLargeShieldDome(){
		return getGenericLevel("defensebuilding", "Cúpula grande de protección");
	}
	
	public int getAntiBallisticMissileQuantity(){
		return getGenericLevel("defensebuilding", "Misiles antibalísticos");
	}
	
	public int getInterPlanetaryMissileQuantity(){
		return getGenericLevel("defensebuilding", "Misil interplanetario");
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/// SENDING FLEET HELPER
	///
	public long getFleetRemainingResources(){
		Element eRemResources = source.getElementById("remainingresources");
		if ( eRemResources == null ) return -1;
		Element underMark = eRemResources.getFirstElementByClass("undermark");
		if ( underMark == null ) return -1;
		return Integer.parseInt(underMark.getContent().toString());
	}
	
	private int getGenericLevel(String elementId, String textLabelTag){
		Element e = source.getElementById(elementId);
		if ( e == null )
			return -1;
		List<Element> levelElements = e.getAllElementsByClass("level");
		
		for (Element element : levelElements) {
			Element textLabel = element.getFirstElementByClass("textlabel");
			
			if ( textLabel.getContent().toString().contains(textLabelTag)){
				int i = element.getContent().toString().lastIndexOf(textLabelTag) + textLabelTag.length();
				if ( i == -1 )
					return -1;
				
				String tmp = element.getContent().toString().substring(i);
				i = tmp.indexOf('>');
				if (i == -1)
					return -1;
				tmp = tmp.substring(i+1);
				
				i = tmp.indexOf('<');
				if ( i != -1 )
					tmp = tmp.substring(0,i);
				return Integer.parseInt(tmp.trim());
			}
			
		}
		return -1;
	}

	public static void main(String[] args) throws Exception {
		StringBuilder buildings = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/buildings.html"));
		
		OgameResponseParser buildingsParser = new OgameResponseParser(buildings.toString());
		System.out.println("Metal = ["+buildingsParser.getMetalResources()+"]");
		System.out.println("Crystal = ["+buildingsParser.getCrystalResources()+"]");
		System.out.println("Deuterium = ["+buildingsParser.getDeuteriumResources()+"]");
		System.out.println("Mina metal = ["+buildingsParser.getMetalMineLevel()+"]");
		System.out.println("Mina cristal = ["+buildingsParser.getCrystalMineLevel()+"]");
		System.out.println("Sint Deuterio = ["+buildingsParser.getDeuteriumSynthLevel()+"]");
		System.out.println("Planta solar = ["+buildingsParser.getSolarPlantLevel()+"]");
		System.out.println("Planta fusion = ["+buildingsParser.getFusionPlantLevel()+"]");
		System.out.println("Almacen metal = ["+buildingsParser.getMetalStorageLevel()+"]");
		System.out.println("Almacen Cristal = ["+buildingsParser.getCrystalStorageLevel()+"]");
		System.out.println("Cont Deuterio = ["+buildingsParser.getDeuteriumStorageLevel()+"]");

		StringBuilder facilities = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/facilities.html"));
		OgameResponseParser facilitiesParser = new OgameResponseParser(facilities.toString());
		System.out.println("Fábrica de Robots = ["+facilitiesParser.getRobotFactoryLevel()+"]");
		System.out.println("Hangar = ["+facilitiesParser.getHangarLevel()+"]");
		System.out.println("Laboratorio = ["+facilitiesParser.getResearchLabLevel()+"]");
		System.out.println("Silo = ["+facilitiesParser.getSiloLevel()+"]");
		System.out.println("Fábrica Nanobots = ["+facilitiesParser.getNanobotFactoryLevel()+"]");
		System.out.println("Terraformer = ["+facilitiesParser.getTerraformerLevel()+"]");
		
		StringBuilder ships = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/hangar.html"));
		OgameResponseParser shipsParser = new OgameResponseParser(ships.toString());
		System.out.println("Cazador Ligero = ["+shipsParser.getLightFighterQuantity()+"]");
		System.out.println("Cazador Pesado = ["+shipsParser.getHeavyFighterQuantity()+"]");
		System.out.println("Crucero = ["+shipsParser.getCruiserQuantity()+"]");
		System.out.println("Nave Batalla = ["+shipsParser.getBattleShipQuantity()+"]");
		System.out.println("Acorazado = ["+shipsParser.getBattleCruiserQuantity()+"]");
		System.out.println("Bombardero = ["+shipsParser.getBomberQuantity()+"]");
		System.out.println("Destructor = ["+shipsParser.getDestroyerQuantity()+"]");
		System.out.println("Estrella Muerte = ["+shipsParser.getDeathStarQuantity()+"]");
		System.out.println("Nave Pequeña Carga = ["+shipsParser.getSmallCargoQuantity()+"]");
		System.out.println("Nave Grande Carga = ["+shipsParser.getLargeCargoQuantity()+"]");
		System.out.println("Colonizador = ["+shipsParser.getColonyShipQuantity()+"]");
		System.out.println("Reciclador = ["+shipsParser.getRecyclerQuantity()+"]");
		System.out.println("Sonda Espionaje = ["+shipsParser.getEspionageProbeQuantity()+"]");
		System.out.println("Satelite Solar = ["+shipsParser.getSolarSatelliteQuantity()+"]");
		
		StringBuilder research = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/research.html"));
		OgameResponseParser researchParser = new OgameResponseParser(research.toString());
		System.out.println("Tecnología de energía= ["+researchParser.getEnergyTechnology()+"]");
		System.out.println("Tecnología láser = ["+researchParser.getLaserTechnology()+"]");
		System.out.println("Tecnología iónica = ["+researchParser.getIonTechnology()+"]");
		System.out.println("Tecnología de hiperespacio = ["+researchParser.getHyperSpaceTechnology()+"]");
		System.out.println("Tecnologiía de plasma = ["+researchParser.getPlasmaTechnology()+"]");

		System.out.println("Motor de combustión = ["+researchParser.getCombustionDrive()+"]");
		System.out.println("Motor de impulso = ["+researchParser.getImpulseDrive()+"]");
		System.out.println("Propulsor Hiperespacial = ["+researchParser.getHyperSpaceDrive()+"]");
		
		System.out.println("Tecnología de espionaje = ["+researchParser.getEspionageTechnology()+"]");
		System.out.println("Tecnología de computación = ["+researchParser.getComputerTechnology()+"]");
		System.out.println("Astrofísica = ["+researchParser.getAstrophysics()+"]");
		System.out.println("Red de investigación intergaláctica = ["+researchParser.getIntergalacticResearchNetwork()+"]");
		System.out.println("Tecnología de gravitón = ["+researchParser.getGravitonTechnology()+"]");

		System.out.println("Tecnología militar = ["+researchParser.getWeaponTechnology()+"]");
		System.out.println("Tecnología de defensa = ["+researchParser.getShieldingTechnology()+"]");
		System.out.println("Tecnología de blindaje = ["+researchParser.getArmourTechnology()+"]");
		
		StringBuilder defense = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/defense.html"));
		OgameResponseParser defenseParser = new OgameResponseParser(defense.toString());
		System.out.println("Lanzamisiles = ["+defenseParser.getRocketLauncherQuantity()+"]");
		System.out.println("Láser pequeño = ["+defenseParser.getLightLaserQuantity()+"]");
		System.out.println("Láser grande = ["+defenseParser.getHeavyLaserQuantity()+"]");
		System.out.println("Cañón Gauss = ["+defenseParser.getGaussCannonQuantity()+"]");
		System.out.println("Cañón iónico = ["+defenseParser.getIonCannonQuantity()+"]");

		System.out.println("Cañón de plasma = ["+defenseParser.getPlasmaTurretQuantity()+"]");
		System.out.println("Cúpula pequeña de protección = ["+defenseParser.getSmallShieldDome()+"]");
		System.out.println("Cúpula grande de protección = ["+defenseParser.getLargeShieldDome()+"]");
		System.out.println("Misiles antibalísticos = ["+defenseParser.getAntiBallisticMissileQuantity()+"]");
		System.out.println("Misil interplanetario = ["+defenseParser.getInterPlanetaryMissileQuantity()+"]");
		
		StringBuilder fleet3 = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/sendFleet/fleet3.html"));
		OgameResponseParser fleet3Parser = new OgameResponseParser(fleet3.toString());
		System.out.println("Remaining Resources = ["+fleet3Parser.getFleetRemainingResources()+"]");

		
	}
}
